package com.yc.thread.testvolatile;

import lombok.Data;

import java.util.concurrent.*;

/**
 * test volatile
 * when multiple thread change the value, the other thread will get new value?
 * @author chenyuan
 */
@Data
public class MultipleThreadVolatile {

    private int num1;
    private int num2;
    private volatile int num3;

    public MultipleThreadVolatile(int num1, int num2, int num3) {
        this.num1 = num1;
        this.num2 = num2;
        this.num3 = num3;
    }

    public void totalNum() {
        int total = this.num3;
//        total += num1 * 2;
//        total += num2 * 4;
        System.out.println(Thread.currentThread().getName() + "===total=" + total);
    }

    public static void main(String[] args) {
//        MultipleThreadVolatile multipleThreadVolatile1 = new MultipleThreadVolatile(1, 2, 3);
//        MultipleThreadVolatile multipleThreadVolatile2 = new MultipleThreadVolatile(2, 3, 4);
//        MultipleThreadVolatile multipleThreadVolatile3 = new MultipleThreadVolatile(3, 4, 5);
//        Thread t1 = new Thread(multipleThreadVolatile1:: totalNum, "test1");
//        Thread t2 = new Thread(multipleThreadVolatile2:: totalNum, "test2");
//        Thread t3 = new Thread(multipleThreadVolatile3:: totalNum, "test3");

        BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(3);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 1L, TimeUnit.SECONDS,  blockingQueue, new MyThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        executor.prestartAllCoreThreads(); // 预启动所有核心线程
        for (int i = 0; i < 20; i++) {
            MultipleThreadVolatile multipleThreadVolatile0 = new MultipleThreadVolatile(i + 1, i + 2, i + 3);
            executor.execute(new Thread(multipleThreadVolatile0:: totalNum, "test" + i));
        }
    }

    static class MyThreadFactory implements ThreadFactory {

        /**
         * Constructs a new {@code Thread}.  Implementations may also initialize
         * priority, name, daemon status, {@code ThreadGroup}, etc.
         *
         * @param r a runnable to be executed by new thread instance
         * @return constructed thread, or {@code null} if the request to
         * create a thread is rejected
         */
        @Override
        public Thread newThread(Runnable r) {

            return new Thread(r);
        }
    }
}
